"""
scheduler_adapter.py - 为Plan类提供数据库适配器支持

这个模块为原接口的Plan类提供数据库适配器支持，使其能够保存数据到新表中。
"""

import logging
import json
import uuid
from datetime import datetime
from contextlib import contextmanager
from uuid import uuid4

from . import db
from .models import (
    ScheduleResult,
    TimeSlot,
    Elderdemand,
    DicNursingAction,
    Attendantskills,
)
from .db_adapter import DatabaseAdapter
from .care_utils import CareUtils

# 设置日志
logger = logging.getLogger(__name__)

# 提供一个安全的事务上下文
@contextmanager
def safe_transaction(session):
    try:
        yield
        session.commit()
    except Exception:
        session.rollback()
        raise

def patch_plan_save_to_database(plan_instance, client_schedules):
    """
    修补Plan类的save_to_database方法，使其使用新的数据库适配器

    Args:
        plan_instance: Plan类实例
        client_schedules: 客户端排班计划
    """
    current_datetime = datetime.now()
    batch_number = get_next_batch_number()

    try:
        with safe_transaction(db.session):
            for elder, schedule in client_schedules.items():
                logging.info(f"Processing schedule for elder {elder}")

                if schedule is None:
                    logging.warning(f"Schedule for elder {elder} is None")
                    continue

                if not isinstance(schedule, list):
                    logging.warning(
                        f"Schedule for elder {elder} is not a list. Type: {type(schedule)}"
                    )
                    continue

                # 排序时间段
                sorted_schedule = sorted(
                    [slot for slot in schedule if slot is not None],
                    key=lambda x: x["TimeSlot"] if "TimeSlot" in x else "",
                )

                # 使用数据库适配器保存到两个表
                schedule_result, care_schedule_result = DatabaseAdapter.save_schedule_result(
                    elder_id=elder,
                    schedule_date=current_datetime,
                    schedule_data=json.dumps(sorted_schedule),
                    plan_date=datetime.now().date(),
                    batch_number=batch_number
                )

                logging.info(f"Created schedule result: {schedule_result.id}")

                # 保存时间段
                for index, slot in enumerate(sorted_schedule):
                    if (
                        "TimeSlot" in slot
                        and "Activity" in slot
                        and "ActivityId" in slot
                        and "Caregiver" in slot
                        and "CaregiverId" in slot
                    ):
                        # 使用数据库适配器保存到两个表
                        DatabaseAdapter.save_time_slot(
                            schedule_result_id=schedule_result.id,
                            elder_id=elder,
                            time_slot=slot["TimeSlot"],
                            activity=slot["Activity"],
                            activity_id=slot["ActivityId"],
                            caregiver="lack" if slot["CaregiverId"] == "-1" else slot["Caregiver"],
                            caregiver_id=slot["CaregiverId"],
                            time_order=index,
                            schedule_date=current_datetime,
                            plan_date=datetime.now().date(),
                            batch_number=batch_number
                        )
                    else:
                        logging.warning(
                            f"Incomplete slot data for elder {elder} at index {index}: {slot}"
                        )

        # 更新Redis中的时间和标志
        try:
            from .redis_utils import set_update_time, set_update_flag
            set_update_time()
            set_update_flag()
        except Exception as e:
            logging.warning(f"Failed to update Redis: {str(e)}")

        return True
    except Exception as e:
        logging.error(f"Failed to save schedule: {str(e)}")
        return False

def get_next_batch_number():
    """获取下一个批次号

    Returns:
        int: 下一个批次号
    """
    try:
        # 查询当前最大批次号
        max_batch = db.session.query(db.func.max(ScheduleResult.batch_number)).scalar()
        if max_batch is None:
            return 1
        return max_batch + 1
    except Exception as e:
        logger.error(f"获取下一个批次号时出错: {str(e)}")
        return 1

def patch_plan_load_nursing_actions(plan_instance):
    """
    修补Plan类的load_nursing_actions方法，使其使用新的数据库适配器

    Args:
        plan_instance: Plan类实例

    Returns:
        dict: 护理动作字典
    """
    from .scheduler import Activity

    nursing_actions = {}

    try:
        # 从care_gb_nursing_action表获取护理动作
        actions = DicNursingAction.query.all()
        logger.info(f"从care_gb_nursing_action表获取到 {len(actions)} 个护理动作")

        for action in actions:
            nursing_actions[action.id] = Activity(
                name=action.name,
                duration=30,  # 修改为30分钟
                required_skill=str(action.id),
            )

        # 确保关键活动存在
        if 8 not in nursing_actions:
            nursing_actions[8] = Activity(name="饮食", duration=30, required_skill="8")

        if 10 not in nursing_actions:
            nursing_actions[10] = Activity(name="睡眠", duration=30, required_skill="10")

        logging.info(
            f"Loaded nursing actions: {[(id, action.name) for id, action in list(nursing_actions.items())[:5]]}..."
        )
        return nursing_actions
    except Exception as e:
        logger.error(f"加载护理动作时出错: {str(e)}")
        # 创建默认的护理动作
        nursing_actions = {
            8: Activity(name="饮食", duration=30, required_skill="8"),
            10: Activity(name="睡眠", duration=30, required_skill="10")
        }
        return nursing_actions

def patch_plan_load_elder_actions(plan_instance):
    """
    修补Plan类的_load_elder_actions方法，使其使用新的数据库适配器

    Args:
        plan_instance: Plan类实例

    Returns:
        dict: 老人护理动作字典
    """
    elder_actions = {}

    try:
        # 从care_elder_demand表获取老人需求
        elder_demands = Elderdemand.query.all()
        logger.info(f"从care_elder_demand表获取到 {len(elder_demands)} 个老人需求")

        for demand in elder_demands:
            if demand.elder not in elder_actions:
                elder_actions[demand.elder] = set()
            if demand.actions:
                action_ids = [
                    int(action_id.strip())
                    for action_id in demand.actions.split(",")
                    if action_id.strip() and action_id.strip().isdigit()
                ]
                elder_actions[demand.elder].update(action_ids)
            else:
                logging.warning(f"找不到护理动作 {demand.elder}")

        return elder_actions
    except Exception as e:
        logger.error(f"加载老人护理动作时出错: {str(e)}")
        return {}

def apply_patches():
    """应用所有补丁"""
    from .scheduler import Plan

    # 保存原始方法
    original_save_to_database = Plan.save_to_database
    original_load_nursing_actions = Plan.load_nursing_actions
    original_load_elder_actions = Plan._load_elder_actions

    # 应用补丁
    Plan.save_to_database = patch_plan_save_to_database
    Plan.load_nursing_actions = patch_plan_load_nursing_actions
    Plan._load_elder_actions = patch_plan_load_elder_actions

    logger.info("已应用Plan类的补丁")

    return {
        "original_save_to_database": original_save_to_database,
        "original_load_nursing_actions": original_load_nursing_actions,
        "original_load_elder_actions": original_load_elder_actions,
    }

def remove_patches(original_methods):
    """移除所有补丁"""
    from .scheduler import Plan

    # 恢复原始方法
    Plan.save_to_database = original_methods["original_save_to_database"]
    Plan.load_nursing_actions = original_methods["original_load_nursing_actions"]
    Plan._load_elder_actions = original_methods["original_load_elder_actions"]

    logger.info("已移除Plan类的补丁")
